{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import spacy\n",
    "from sklearn.base import TransformerMixin\n",
    "\n",
    "# Create a spaCy parser\n",
    "nlp = spacy.load('en')\n",
    "\n",
    "\n",
    "class BagOfWords(TransformerMixin):\n",
    "    def fit(self, X, y=None):\n",
    "        return self\n",
    "    \n",
    "    def transform(self, X):\n",
    "        results = []\n",
    "        for document in X:\n",
    "            row = {}\n",
    "            for word in list(nlp(document, tag=False, parse=False, entity=False)):\n",
    "                if len(word.text.strip()):\n",
    "                    row[word.text] = True\n",
    "            results.append(row)\n",
    "        return results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.feature_extraction import DictVectorizer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.naive_bayes import BernoulliNB"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import os\n",
    "input_filename = os.path.join(os.path.expanduser(\"~\"), \"data/datasets\", \"twitter\", \"python_tweets.json\")\n",
    "labels_filename = os.path.join(os.path.expanduser(\"~\"), \"data/datasets\", \"twitter\", \"python_classes.json\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import json\n",
    "\n",
    "tweets = []\n",
    "with open(input_filename) as inf:\n",
    "    for line in inf:\n",
    "        if len(line.strip()) == 0: continue\n",
    "        tweets.append(json.loads(line)['text'])\n",
    "\n",
    "with open(labels_filename) as inf:\n",
    "    labels = json.load(inf)\n",
    "\n",
    "# Ensure only classified tweets are loaded\n",
    "tweets = tweets[:len(labels)]\n",
    "assert len(tweets) == len(labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.pipeline import Pipeline\n",
    "\n",
    "pipeline = Pipeline([('bag-of-words', BagOfWords()), ('vectorizer', DictVectorizer()), ('naive-bayes', BernoulliNB()) ])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Score: 0.684\n"
     ]
    }
   ],
   "source": [
    "from sklearn.cross_validation import cross_val_score\n",
    "scores = cross_val_score(pipeline, tweets, labels, scoring='f1')\n",
    "#We then print out the average of the scores:\n",
    "import numpy as np\n",
    "print(\"Score: {:.3f}\".format(np.mean(scores)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model = pipeline.fit(tweets, labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "nb = model.named_steps['naive-bayes']\n",
    "feature_probabilities = nb.feature_log_prob_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "top_features = np.argsort(-nb.feature_log_prob_[1])[:50]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "dv = model.named_steps['vectorizer']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 : 0.53125\n",
      "1 # 0.51875\n",
      "2 Python 0.4875\n",
      "3 python 0.40625\n",
      "4 RT 0.26875\n",
      "5 in 0.21875\n",
      "6 - 0.2\n",
      "7 to 0.19375\n",
      "8 , 0.1875\n",
      "9 for 0.175\n",
      "10 and 0.1375\n",
      "11 . 0.125\n",
      "12 ? 0.11875\n",
      "13 the 0.10625\n",
      "14 ) 0.10625\n",
      "15 ( 0.10625\n",
      "16 of 0.1\n",
      "17 with 0.1\n",
      "18 I 0.08125\n",
      "19 a 0.08125\n",
      "20 A 0.06875\n",
      "21 via 0.06875\n",
      "22 jobs 0.0625\n",
      "23 ! 0.05625\n",
      "24 an 0.05625\n",
      "25 from 0.05\n",
      "26 How 0.05\n",
      "27 Data 0.05\n",
      "28 this 0.05\n",
      "29 Developer 0.05\n",
      "30 data 0.05\n",
      "31 current 0.04375\n",
      "32 installing 0.04375\n",
      "33 Top 0.04375\n",
      "34 by 0.04375\n",
      "35 library 0.04375\n",
      "36 status 0.04375\n",
      "37 30 0.0375\n",
      "38 And 0.0375\n",
      "39 C++ 0.0375\n",
      "40 Tech 0.0375\n",
      "41 Job 0.0375\n",
      "42 or 0.0375\n",
      "43 looking 0.0375\n",
      "44 3 0.0375\n",
      "45 [ 0.0375\n",
      "46 ] 0.0375\n",
      "47 @shiftkey 0.0375\n",
      "48 Django 0.0375\n",
      "49 Engineer 0.0375\n"
     ]
    }
   ],
   "source": [
    "for i, feature_index in enumerate(top_features):\n",
    "    print(i, dv.feature_names_[feature_index], np.exp(feature_probabilities[1][feature_index]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
